#pragma once

/* 假的层 */
#include <metalc/mlayer/_mlayer.h>
/* arrcache用于缓存 */
#include <metalc/block/arrcache.h>
#include <metalc/block/kslab.h>

/* 输入锁 */
#ifndef SLAB_APDS
	#define SLAB_APDS			apdsspin
#endif

#define SLAB_PRINT(...)		INFO(__VA_ARGS__)
// #define SLAB_PRINT(...)		dbg_printf(__VA_ARGS__)
/* 直接定义锁和同步函数，这样就不用通过DEF定义宏函数方式传入 */
MLAYER_SYNC(slab, SLAB_APDS)
OU2INFUN(cls, slab_cls)

#define KSLAB_USE_CACHEARR

typedef const struct slab_conf {
	const size_t slab_size;
	const size_t slab_max_cachelimit;
	const hword_t slab_free_retained_perclass;
	const szcls_t slab_totalcls;
	const size_t max_sz;
} slab_conf_t;

typedef struct slab_clsobj {
	struct
	{
		slab_apds_t lock;
		
#ifdef KSLAB_USECACHE_LIST
		skplist_t *cache_list;
#else
	#ifdef KSLAB_USE_CACHEARR
		// arrcache_t cache_arr;
		word_t cache_arrspace[ARRCACHE_SIZE/sizeof(word_t)]; 
	#endif
		word_t cache_cnt;
#endif

		dlist_t non_empty;

		dlist_t full;
		
		size_t full_cnt;
		
		szcls_t cls; /* 当前szcls */
	} CACHE_ALIGNED;
} slab_clsobj_t;

/* 是cls数组 */
typedef slab_clsobj_t slab_obj_t;

SAI size_t slab_obj_size(slab_conf_t *conf) {
	return conf->slab_totalcls * sizeof(slab_clsobj_t);
}
#ifdef KSLAB_USE_CACHEARR
SAI arrcache_t *slab_clsobj_cachearr(slab_clsobj_t *l){
	return (arrcache_t *)(&l->cache_arrspace[0]);
}
#endif
SAI kslab_t *kslab_byptr(void *ptr, slab_conf_t *conf) {
	return (kslab_t *)((paddr_t)ptr & (~(conf->slab_size - 1UL)));
}
SAI void slab_clsobj_init(slab_clsobj_t *co, szcls_t cls) {
	ASSERT(co);
	MLAYER_APDS_INIT(SLAB_APDS, &co->lock, sizeof(co->lock));
#ifdef KSLAB_USECACHE_LIST
	p->szcls[i].cache_list = NULL;
#else
	#ifdef KSLAB_USE_CACHEARR
		arrcache_init(&co->cache_arrspace[0], ARRCACHE_SIZE, ARRCACHE_STATIC_MAX_NR);
	#endif
#endif
	co->cache_cnt = 0;
	dlist_init(&co->non_empty);
	dlist_init(&co->full);
	co->full_cnt = 0;
	co->cls = cls;
}

SAI NO_UNROLL slab_obj_t *slab_init(void *mem, size_t size, slab_conf_t *conf) {
	if (!mem || size < slab_obj_size(conf)) return NULL;
	slab_obj_t *l = (slab_obj_t *)mem;

	for (word_t idx = 0; idx < conf->slab_totalcls; idx++) {
		slab_clsobj_init(&l[idx], idx);
	}
	return l;
}

SAI uvoid *slab_oomhandler(mreq_t *req, slab_conf_t *conf, const mlfunc_t * cont)
{	
	uvoid *ret;
	// 向上层请求slab
	req->size = conf->slab_size;
	req->align = conf->slab_size;
	req->nr = 1;
	ret = cont->lalloc(req);
	SLAB_PRINT("[slab] oom get %p, size %lx\n", ret, conf->slab_size);
	// dbg_printf("[slab] oom get %p, size %lx\n", ret, conf->slab_size);
	return ret;
}

SAI void slab_fomhandler(mreq_t *req, kslab_t *s, hword_t nr, slab_conf_t *conf, const mlfunc_t * cont){
	/* 批量释放 */
	// s->node.prev->next = NULL;
	s->node.prev->next = NULL_PTR;
	/* 确保释放的节点数量满足 */
	// ASSERT(slist_len_noloop((slist_t *)&s->node) == nr);
	
	req->ptr = s;
	req->sptr = s->node.prev;
	req->size = conf->slab_size;
	req->nr = nr;
	SLAB_PRINT("[slab] oof return %p - %p, size %lx, nr%x\n", req->ptr, req->sptr, req->size, nr);
	// dbg_printf("[slab] oof return %p - %p, size %lx, nr%x\n", req->ptr, req->sptr, req->size, nr);
	cont->lfree(req);
}

STA_INFUN(slab_critsec)
kslab_t *(* const insert_nonempty)(slab_clsobj_t *co, kslab_t *s);
dlist_t *(* const alloc_batch)(slab_clsobj_t *co, hword_t nr);
kslab_t *(* const free_batch)(slab_clsobj_t *co, slist_t *head, slist_t *tail, hword_t nr, hword_t unit_size);
END_INFUN(slab_critsec)

SAI kslab_t *__slab_insert_nonempty(slab_clsobj_t *co, kslab_t *s) {
	// 插入到合适位置
	// __mdlist_add(&s->node, &co->non_empty, c->non_empty.next);
	__dlist_insert(&co->non_empty, &s->node, &s->node, co->non_empty.next);
	return NULL_PTR;
}

/* 申请多少个对象 */
SAI dlist_t *__slab_alloc_batch(slab_clsobj_t *co, hword_t hnr) {
	kslab_t *s;
	size_t nr = hnr;
	size_t pop_nr = 0;
	slist_t *tphead = NULL_PTR;
	slist_t *tptail = (slist_t *)&tphead;

	slist_t *thead = NULL_PTR;
	slist_t *ttail = NULL_PTR;

	size_t pnr;
	dlist_t *ret;

RETRY:
#ifdef KSLAB_USE_CACHE_LIST
	/* TODO: 还未修改 */
	// 先检查
	if (c->cache_list)
	{
		// *phead = c->cache_list;
		// *ptail = c->cache_list->skip_tail;
		// connect to tail

		skplist_node_t *sltail = c->cache_list->skip_tail;
		tptail->next = (slist_t *)c->cache_list;
		tptail = (slist_t *)sltail;

		pop_nr += sltail->cnt;

		c->cache_cnt -= sltail->cnt;
		c->cache_list = sltail->next;

		if (pop_nr < nr)
		{
			// 重新尝试
			goto RETRY;
		}
		// return pop_nr;
	}
	else
#else
	#ifdef KSLAB_USE_CACHEARR
	/* 先尝试从arrcache中取 */
	
	pnr = arrcache_pop_batch(slab_clsobj_cachearr(co), &thead, &ttail, nr - pop_nr);
	if (pnr != 0)
	{
		// SLAB_PRINT("[slab] poped %p - %p, nr %x from arrcache %p\n", thead, ttail, nr, slab_clsobj_cachearr(co));
		/* 批量从arrcache中取 */
		ASSERT(thead && ttail);
		pop_nr += pnr;
		// link
		// ASSERT(slist_len_noloop(thead) == pnr);
		tptail->next = thead;
		tptail = ttail;
		// ASSERT(slist_len_noloop(tphead) == pop_nr);
		co->cache_cnt -= pnr;
		if (pop_nr < nr)
			goto RETRY;
	}
	else
	#endif
#endif
	{
		/* 队列中取 */
		if (!list_is_empty(&co->non_empty)) // !empty
		{
			/* 从非空中取一个 */
			s = list_entry(kslab_t, co->non_empty.next, node);

			ASSERT(nr > pop_nr);
			pnr = kslab_alloc_batch(s, &thead, &ttail, nr - pop_nr);
			ASSERT(pnr);
			pop_nr += pnr;
			ASSERT(thead && ttail);

			// 连接
			tptail->next = thead;
			tptail = ttail;

			if (kslab_is_empty(s))
			{	
				// ASSERT(s->used_offst == (1UL << s->size_order));
				ASSERT(s->used_nr == s->max_nr);
				// 插入到empty
				// debug_fprintf(stderr, "abandoned span %p\n", s);
				dlist_del(s->node.prev, s->node.next);
				
				// 插到最后
				//__mdlist_add(&s->node, &c->empty, c->empty.next);
				dlist_init(&s->node);
			} else{
				ASSERT(s->flist != NULL_PTR);
			}
			if (pop_nr < nr)
			{
				goto RETRY;
			}
		}
		else if (!list_is_empty(&co->full)) {
			/* 到full队列中查找 */
			s = list_entry(kslab_t, co->full.next, node);
			pnr = kslab_alloc_batch(s, &thead, &ttail, nr - pop_nr);
			ASSERT(pnr != 0);
			pop_nr += pnr;
			ASSERT(thead && ttail);

			// 连接
			tptail->next = thead;
			tptail = ttail;

			/* 减少 */
			co->full_cnt--;

			// __mdlist_del(s->node.prev, s->node.next);
			dlist_del(s->node.prev, s->node.next);
			
			if (kslab_is_empty(s)){
				// ASSERT(s->used_offst == (1UL << s->size_order));
				//__mdlist_add(&s->node, &c->empty, c->empty.next);
				dlist_init(&s->node);
			}
			else{
				// __mdlist_add(&s->node, &c->non_empty, c->non_empty.next);
				/* 非空插入到非空队列 */
				__dlist_insert(&co->non_empty, &s->node, &s->node, co->non_empty.next);

			}
		
			if (pop_nr < nr)
			{
				/* 重新尝试 */
				goto RETRY;
			}
		}
	}

RET:
	/* 利用ret->prev 连接tail */
	/* tail->next用于计数 */
	/* 连接 */

	if (!tphead) {
		ASSERT(pop_nr == 0);
		SLAB_PRINT("[slab] alloc batch get nothing\n");
		return NULL;
	}
	ret = (dlist_t *)tphead;
	
	/* 连接尾部 */
	ret->prev = (dlist_t *)tptail;

	/* TODO:可以消除 */
	tptail->next = NULL;
	// ASSERT(slist_len_noloop(tphead) == pop_nr);
	

	tptail->next = (slist_t *)(pop_nr);
	SLAB_PRINT("[slab] alloc batch get %p to %p, nr %lx\n", tphead, tptail, pop_nr);
	return ret;
}

/* 释放多少个对象 */
SAI kslab_t *__slab_free_batch(slab_clsobj_t *co, slist_t *head, slist_t *tail, hword_t nr, hword_t unit_size, slab_conf_t *conf){
	// 循环挨个释放
	kslab_t *s;
	dlist_t ret;
	word_t tnr = 0;
	slist_t *next;
	slist_t *thdr;
	// 复用传参
#ifdef KSLAB_USE_CACHE_LIST
	// fprintf(stderr, "[slab] free %u nr %u\n", unit_size, nr);
	word_t limit = SLAB_MAX_CACHELIMIT >> LOG2_ALIGN(unit_size);
	if ((co->cache_cnt < limit) && (nr > 1))
	{
		//
		assert(nr > 1);
		hdr->skip_tail->next = co->cache_list;

		co->cache_list = hdr;
		co->cache_cnt += nr;

		return NULL;
	}
	else
	{
		// 替换
		if (nr == 1)
		{
			if (co->cache_list)
			{
				skiplisthead_t *tphdr = co->cache_list;

				slist_t *tptail = (slist_t *)tphdr->skip_tail;
				hword_t pop_nr = tphdr->skip_tail->cnt;

				co->cache_list = tphdr->skip_tail->next;
				co->cache_cnt -= pop_nr;

				tptail->next = (slist_t *)hdr;
				hdr = tphdr;
				nr += pop_nr;
				//return pop_nr;
				// return NULL;
			}
			else
				hdr->next = NULL;
		}
	}
#else
#ifdef KSLAB_USE_CACHEARR
	// ASSERT(slist_len_noloop(head) == nr);
	word_t limit = conf->slab_max_cachelimit >> log2_align(unit_size);

	/* 没有超限 */
	// ASSERT(co->cache_cnt < limit);
	if (co->cache_cnt <= limit)
	{	
		// ASSERT(nr != 1);
		bool_t t = arrcache_push_batch(slab_clsobj_cachearr(co), head, tail, nr);

		if (t)
		{
			SLAB_PRINT("[slab]  push %p - %p, nr %x into arrcache %p\n", head, tail, nr, slab_clsobj_cachearr(co));
			/* 插入cache list */
			co->cache_cnt += nr;
			return NULL;
		}
		SLAB_PRINT("[slab] try push %p - %p, nr %x into arrcache %p failed, arrcache is full\n", head, tail, nr, slab_clsobj_cachearr(co));
	}
	
	/* 超限后全部弹出 */
	slist_t *hd = NULL;
	slist_t *tl = NULL;

	size_t pop_nr = arrcache_pop_batch(slab_clsobj_cachearr(co), &hd, &tl, -1);
	ASSERT(pop_nr);
	nr += pop_nr;
	
	tail->next = hd;
	tl->next = NULL;
	co->cache_cnt -= pop_nr;

#endif

#endif
	/* slow path, 逐个插回 */
	ASSERT(nr != 0);

	// ASSERT(slist_len_noloop(head) == nr);
	thdr = (slist_t *)head;
	dlist_init(&ret);
	/* 逐个释放 */
	for (word_t i = 0; i < nr; i++)
	{
		ASSERT(thdr);
		next = atm_ld(&thdr->next);
		s = kslab_byptr((void *)thdr, conf);
		bool_t is_empty = kslab_is_empty(s);
		SLAB_PRINT("[slab] try free %p in slab %p\n", thdr, s);
		if (kslab_free_batch(s, thdr, thdr, 1))
		{
			// 满了,移动到满的
			SLAB_PRINT("[slab] free %p from span %p, prev %p, next %p\n", thdr, &s->node, s->node.prev, s->node.next);

			// FIX: 这里有问题!!!

			/* 先前不是空的才需要移除 */
			/* 通过dlist确保删除无效 */
			dlist_del(s->node.prev, s->node.next);

			/* 插入到队列 */
			// dbg_printf("[slab] free a full slab %p, full cnt %lx\n", s, co->full_cnt);
			if (co->full_cnt >= conf->slab_free_retained_perclass)
			{	
				/* TODO: 可改成最近未使用出队 */
				__dlist_insert(&ret, &s->node, &s->node, ret.next);
				tnr++;
				SLAB_PRINT("[slab]full fred slab %p insert to free list, prev %p, next %p, nr %ld\n", &s->node, s->node.prev, s->node.next, tnr);
				// dbg_printf("[slab]full fred slab %p insert to free list, prev %p, next %p, nr %ld\n", &s->node, s->node.prev, s->node.next, tnr);
			}
			else
			{
				/* 初始化插回去 */
				kslab_init(s, conf->slab_size, co->cls, s->unit_size);
				co->full_cnt++;
				__dlist_insert(&co->full, &s->node, &s->node, co->full.next);
				SLAB_PRINT("[slab] %p insert to full list, prev %p, next %p, nr %ld\n", &s->node, s->node.prev, s->node.next, tnr);
			}

			// !already in non empty
		}
		else
		{
			// 未满且之前是空的
			if (is_empty)
			{
				// ASSERT(s->used_offst == (1UL << s->size_order));

				ASSERT(s->flist != NULL_PTR);
				//
				// 如果之前是空的
				//__mdlist_del(s->node.prev, s->node.next);
				__dlist_insert(&co->non_empty, &s->node, &s->node, co->non_empty.next);
				SLAB_PRINT("[slab] reclaim span %p, prev %p, next %p\n", s, s->node.prev, s->node.next);
			}
		}
		thdr = next;
		/* 超过一定限度则向上归还 */
	}
	if (!list_is_empty(&ret))
	{
		// FIX: 这里必须next
		// kslab_t *t = list_entry(ret.next, kslab_t, node);
		// kslab_t *next;
		// for (word_t i = 0; i < tnr; i++)
		// {

		//	 // printf("free span%lx\n",s);
		//	 next = list_entry(t->node.next, kslab_t, node);

		//	 debug_fprintf(stderr, "list %lx, next %p, oof_nr%lu\n", t, next, i);
		//	 t = next;
		// }
		kslab_t *ret_head = list_entry(kslab_t, ret.next, node);
		
		SLAB_PRINT("[slab] return ret_head %p, nr %lx\n", ret_head, tnr);
		/* 连接成环 */
		// dlist_del(ret.prev, ret.next);
		ret_head->node.prev = ret.prev;
		ret.prev->next = &ret_head->node;
		// ret_head->node.next = rethead;
		ret_head->dnode_cnt = tnr;
		return ret_head;
	}
	return NULL;
	// return (kslab_t *)ret.next;
}
/* DEF slab临界区 */
/* 定义临界区 */
#define DEF_SLAB_CRTISEC(name, apds_comp, pconf)	\
SAI kslab_t *name##_slab_free_batch(slab_clsobj_t *co, slist_t *head, slist_t *tail, hword_t nr, hword_t unit_size){\
	return __slab_free_batch(co, head, tail, nr, unit_size, pconf);\
}\
static apdsret_t name##_slab_alloc_batch_crit(APDSFUNC_ARGLIST){\
	slab_clsobj_t *co = (slab_clsobj_t *)arg0;\
	hword_t nr = (hword_t)arg1;\
	PARAM_USED(arg2, arg3);\
	return (apdsret_t)__slab_alloc_batch(co, nr);\
}\
static apdsret_t name##_slab_free_batch_crit(APDSFUNC_ARGLIST){\
	slab_clsobj_t *co = (slab_clsobj_t *)arg0;\
	slist_t *head = (slist_t *)arg1;\
	slist_t *tail = (slist_t *)arg2;\
	hword_t nr = word_high(arg3);\
	hword_t unit_size = word_low(arg3);\
	return (apdsret_t)name##_slab_free_batch(co, head, tail, nr, unit_size);\
}\
static apdsret_t name##_insert_nonempty_crit(APDSFUNC_ARGLIST){\
	slab_clsobj_t *co = (slab_clsobj_t *)arg0;\
	kslab_t *s = (kslab_t *)arg1;\
	PARAM_USED(arg2, arg3);\
	return (apdsret_t)__slab_insert_nonempty(co, s);\
}\
SAI kslab_t * name##_insert_nonempty(slab_clsobj_t *co, kslab_t *s){\
	APDS_ARGS(apdsarg, co, s);\
	return (kslab_t *)MLAYER_APDS_SYNC(apds_comp, &co->lock, name##_insert_nonempty_crit, apdsarg);\
}\
SAI dlist_t * name##_alloc_batch(slab_clsobj_t *co, hword_t nr){\
	APDS_ARGS(apdsarg, co, nr);\
	return (dlist_t *)MLAYER_APDS_SYNC(apds_comp, &co->lock, name##_slab_alloc_batch_crit, apdsarg);\
}\
SAI kslab_t * name##_free_batch(slab_clsobj_t *co, slist_t *head, slist_t *tail, hword_t nr, hword_t unit_size){\
	APDS_ARGS(apdsarg, co, head, tail, new_word(nr, unit_size));\
	return (kslab_t *)MLAYER_APDS_SYNC(apds_comp, &co->lock, name##_slab_free_batch_crit, apdsarg);\
}\
NEW_INFUN(slab_critsec, name##_critsec, name##_insert_nonempty, name##_alloc_batch, name##_free_batch)


SAI void _slab_pinit(const mlfunc_t * cont, perm_allocf_t *alloc, slab_conf_t *conf, slab_obj_t **pobj){
	/* 创建全局唯一 */
	PARAM_USED(cont);
	if (!*pobj){
		size_t sz = slab_obj_size(conf);
		void *mem = alloc(sz);
		*pobj = slab_init(mem, sz, conf);
	}
	SLAB_PRINT("slab pinit\n");

}
SAI void _slab_tinit(const mlfunc_t * cont){
	PARAM_USED(cont);
	SLAB_PRINT("slab tinit\n");
}

SAI void *_slab_alloc(mreq_t *req, const mlfunc_t * cont, slab_obj_t *slab, slab_conf_t *conf, INFUN(slab_cls, clspol), INFUN(slab_critsec, crit)){
	size_t req_size = req->size;

	/* 自对齐 */
	size_t alignment = req->align;
	if (UNLIKELY(alignment != 0)){
		req_size = align_up(req_size, alignment);
	}

	
	if (__MLAYER_INVALID_REQSZ(conf->max_sz, req_size)) return cont->lalloc(req);
	/* 大于2个字 */
	/* 自对齐方式 */

	szcls_t cls = clspol->sz2cls(req_size);
	size_t aligned_size = clspol->cls2sz(cls);
	size_t nr = req->nr;
	
	SLAB_PRINT("[slab] try alloc %lx, cls %x, cls2sz %lx, nr %lx\n", req_size, cls, aligned_size, req->nr);
	
	/* 对齐后大小必须大于2个字 */
	ASSERT(aligned_size >= sizeof(word_t) * 2);
	ASSERT(cls < conf->slab_totalcls);
	
	dlist_t *ret = crit->alloc_batch(&slab[cls], nr);
	
	slist_t *head = NULL_PTR;
	slist_t *tail = NULL_PTR;
	size_t pop_nr = 0;
	if (ret != NULL){
		head = (slist_t *)ret;
		tail = (slist_t *)ret->prev;
		pop_nr = (size_t)tail->next;
		
		/* 测试 */
		tail->next = NULL_PTR;
		// ASSERT(slist_len_noloop(head) == pop_nr);
	}
	else{
		/* 申请失败，向上申请 */
		kslab_t *n = (kslab_t *)slab_oomhandler(req, conf, cont);
		if (!n) return NULL;
		
		ASSERT(is_ptr_aligned(n, conf->slab_size));
		SLAB_PRINT("[slab] init slab %p, total size %lx, unit_size %lu\n", n, conf->slab_size, aligned_size);
		kslab_init(n, conf->slab_size, cls, aligned_size);
		pop_nr = kslab_alloc_batch(n, &head, &tail, nr);
		ASSERT(n->used_nr == pop_nr);
		if (!kslab_is_empty(n)){
			crit->insert_nonempty(&slab[cls], n);
		}
	}
	SLAB_PRINT("[slab] finished alloc %p, size %lx, nr %lx\n", head, aligned_size, nr);
	if (pop_nr == 0) return NULL;
	
	tail->next = NULL;
	// ASSERT(slist_len_noloop(head) == pop_nr);
	req->ptr = (void *)head;
	req->sptr = (void *)tail;
	req->nr = pop_nr;
	req->size = aligned_size;
	return req->ptr;
}
SAI bool_t _slab_free(mreq_t *req, const mlfunc_t * cont, slab_obj_t *slab, slab_conf_t *conf, INFUN(slab_cls, clspol), INFUN(slab_critsec, crit)){
	size_t get_size = req->size;
	if (MLAYER_INVALID_REQSZ(cont, get_size)) return cont->lfree(req);
	// szcls_t cls = clspol->sz2cls(get_size);
	szcls_t cls = req->cls;
	kslab_t *tmp_slab = kslab_byptr(req->ptr, conf);
	ASSERT(cls == tmp_slab->cls);
	PARAM_USED(clspol);
	// ASSERT(clspol->cls2sz(cls) >= get_size);
	size_t nr = req->nr;
	kslab_t *slab_list = NULL;
	slist_t *head = (slist_t *)req->ptr;
	slist_t *tail = (slist_t *)req->sptr;
	
	SLAB_PRINT("[slab] try free %p - %p, size %lx, cls %x, nr %lx\n", req->ptr, req->sptr, get_size, cls, req->nr);
	ASSERT(head && tail);
	hword_t slab_nr;

	slab_list = crit->free_batch(&slab[cls], head, tail, (hword_t)nr, (hword_t)get_size);


	if (slab_list){
		slab_nr = slab_list->dnode_cnt;
		slab_fomhandler(req, slab_list, slab_nr, conf, cont);
	}
	return TRUE;
}
SAI size_t _slab_sizeof(mreq_t *req, const mlfunc_t * cont, slab_conf_t *conf){
	if (MLAYER_IS_LASTLAYER(cont) || !is_ptr_aligned(req->ptr, conf->slab_size)){
		word_t cls_size = kslab_byptr(req->ptr, conf)->cls_size;
		size_t size = word_low(cls_size);
		szcls_t cls = word_high(cls_size);
		req->cls = cls;
		
		// size_t size = kslab_byptr(req->ptr, conf)->unit_size;
		req->size = size;
		
		ASSERT(size >= sizeof(dword_t));
		SLAB_PRINT("[slab] sizeof %p, sz %lx\n", req->ptr, size);
		return size;
	}
	return cont->lsizeof(req);
}

/* 定义 
 * min_bit - 管理的最小bit位
 * max_bit - 管理的最大bit位
 * cls_comp - szcls策略
 * slab_max_cachelimit - slab最大cache限制
 * slab_free_retained_perclass - 保留free slab个数
 * perm_alloc - 永久对象分配函数
*/
#define DEF_SLAB_MLAYER(name, min_bit, max_bit, cls_comp, slab_max_cachelimit_, slab_free_retained_perclass_, perm_alloc)\
DEF_MLAYER_BASIC(name, BIT(max_bit), 0)\
static slab_obj_t *name##_obj;\
static const slab_conf_t name##_conf = { .slab_totalcls = _clsnr_##cls_comp, .slab_size = BIT(max_bit) * 2,\
.slab_max_cachelimit = slab_max_cachelimit_, .slab_free_retained_perclass = slab_free_retained_perclass_, .max_sz = _maxsz_##cls_comp };\
DEF_SLAB_CRTISEC(name, SLAB_APDS, &name##_conf)\
SAI void name##_pinit(const mlfunc_t * cont){ return _slab_pinit(cont, perm_alloc, &name##_conf, &name##_obj); }\
SAI void name##_tinit(const mlfunc_t * cont){ return _slab_tinit(cont); }\
SAI void *name##_alloc(mreq_t *req, const mlfunc_t * cont){\
	return _slab_alloc(req, cont, name##_obj, &name##_conf, OUFUN_OF(cls_comp), INFUN_OF(name##_critsec));\
}\
SAI bool_t name##_free(mreq_t *req, const mlfunc_t * cont){\
	return _slab_free(req, cont, name##_obj, &name##_conf, OUFUN_OF(cls_comp), INFUN_OF(name##_critsec));\
}\
SAI size_t name##_sizeof(mreq_t *req, const mlfunc_t * cont){\
	return _slab_sizeof(req, cont, &name##_conf); }





